/*
 * @Description: MCP 兼容性服务器实现
 *   核心功能：
 *   1. 支持新客户端无状态 HTTP 请求（POST /mcp）
 *   2. 兼容旧客户端 SSE 长连接（GET /sse + POST /messages）
 *   3. 统一处理 JSON-RPC 2.0 协议请求
 *
 * 设计要点：
 * - 新客户端采用无状态设计，每次请求独立处理
 * - 旧客户端保持长连接状态，通过 sessionId 维持会话
 * - 两种模式共享同一套工具注册系统
 *
 * @Author: 莫若省
 * @date: 2025/9/2
 */

import express from "express";
import cors from 'cors';
// 导入 MCP 协议传输层实现
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
// 导入 MCP 服务生成器
import { generateMcpServer } from "./lib/mcp/index.js";

// 初始化基础 MCP 服务实例（包含已注册的工具）
const server = generateMcpServer();

// ======================
// Express 应用配置
// ======================
const app = express();
// 中间件配置
app.use(express.json());  // 启用 JSON 请求体解析
app.use(cors());         // 启用跨域资源共享

// ======================
// 传统 SSE 模式实现 (旧客户端兼容)
// ======================
/**
 * SSE 会话存储表
 * 用于维护长连接客户端的会话状态
 *
 * 数据结构：
 * {
 *   [sessionId: string]: SSEServerTransport 实例
 * }
 */
const sseTransports: Record<string, SSEServerTransport> = {};

/**
 * SSE 连接建立端点 (GET /sse)
 *
 * 工作流程：
 * 1. 创建 SSE 传输层实例
 * 2. 注册会话到全局管理表
 * 3. 绑定连接关闭事件处理
 * 4. 连接 MCP 服务核心
 */
app.get("/sse", async (req, res) => {
  // 初始化 SSE 传输层（绑定 /messages 消息接收端点）
  const transport = new SSEServerTransport("/messages", res);
  // 会话状态管理
  sseTransports[transport.sessionId] = transport;  // 注册会话
  res.on("close", () => {
    delete sseTransports[transport.sessionId];     // 清理会话资源
  });
  // 连接 MCP 核心服务
  await server.connect(transport);
});

/**
 * SSE 消息接收端点 (POST /messages)
 *
 * 工作流程：
 * 1. 从查询参数获取 sessionId
 * 2. 查找对应的传输层实例
 * 3. 处理消息并返回响应
 */
app.post("/messages", async (req, res) => {
  const sessionId = req.query.sessionId as string;
  const transport = sseTransports[sessionId];

  if (!transport) {
    return res.status(400).json({ error: "Invalid or expired sessionId" });
  }

  await transport.handlePostMessage(req, res, req.body);
});

// ======================
// 无状态 HTTP 模式 (新客户端规范)
// ======================
/**
 * 标准 MCP 接入端点 (POST /mcp)
 *
 * 设计特点：
 * - 无会话状态（stateless）
 * - 每次请求独立创建服务实例
 * - 符合 HTTP/REST 最佳实践
 *
 * 工作流程：
 * 1. 创建无状态传输层实例
 * 2. 绑定连接关闭处理
 * 3. 初始化新服务实例
 * 4. 处理 JSON-RPC 请求
 */
app.all("/mcp", async (req, res) => {
  try {
    // 配置无状态传输层（禁用 sessionId 生成）
    const transport = new StreamableHTTPServerTransport({
      sessionIdGenerator: undefined,  // 关键配置：禁用会话状态
    });

    // 请求生命周期管理
    res.on("close", () => transport.close());

    // 每次请求创建独立服务实例
    const statelessServer = generateMcpServer();

    await statelessServer.connect(transport);

    // 处理 JSON-RPC 协议请求
    await transport.handleRequest(req, res, req.body);
  } catch (err) {
    console.error("[MCP] 请求处理异常:", err);

    // 标准化错误响应（遵循 JSON-RPC 2.0 规范）
    if (!res.headersSent) {
      res.status(500).json({
        jsonrpc: "2.0",
        error: {
          code: -32603,  // 内部错误代码
          message: "Internal server error",
          data: process.env.NODE_ENV === 'development' ? JSON.stringify(err) : undefined
        },
        id: null,  // 表示通知类错误
      });
    }
  }
});

// ======================
// 服务启动与监控
// ======================
const PORT = process.env.PORT ? Number(process.env.PORT) : 8848;
app.listen(PORT, () => {
  console.log(`[MCP] 兼容服务已启动：
  新客户端端点：POST http://localhost:${PORT}/mcp
  旧客户端端点：GET  http://localhost:${PORT}/sse
  监控端点：GET  http://localhost:${PORT}/healthz`);
});

// 简易健康检查端点
app.get('/healthz', (req, res) => {
  res.status(200).json({
    status: 'healthy',
    timestamp: new Date().toISOString()
  });
});